package com.lagou.edu.wwyan.web1.minicat;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 启动类
 */
public class Bootstrap implements LifeCycle{
    private int port = 9080;
//    private Map<String,Servlet> servletMap = new HashMap<>();
    private Server server;

    private Mapper mapper = new Mapper();

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void init() {
//        loadServlet();

        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
        SAXReader saxReader = new SAXReader();

        try {
            server = new Server();
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> serviceElements = rootElement.selectNodes("//Service");
            for (Element serviceElement : serviceElements) {
                List<Element> hostElements = serviceElement.selectNodes("//Host");
                List<Host> hosts = new ArrayList<>();
                for (Element hostElement : hostElements) {
                    String hostName = hostElement.attributeValue("name");
                    String appBase = hostElement.attributeValue("appBase");
                    Host host = new Host(hostName, appBase);


                    mapper.addHost(hostName,host);
                    hosts.add(host);

                    //读取context，这里是直接读取配置的，也可以直接读取host.appBase目录下的所有文件夹
                    List<Element> contextElements = hostElement.selectNodes("Context");
                    for (Element contextElement : contextElements) {
                        String docBase = contextElement.attributeValue("docBase");
                        Context context = new Context(contextElement.attributeValue("path"), docBase);
                        loadWebServlet(appBase,context);
                        host.addContext(context);
                        mapper.addContext(hostName,context);
                    }
                    //加载目录下没有配置的其他文件夹
                    loadWebAppsDir(host);

                }
                Element connectorElement = (Element) rootElement.selectSingleNode("//Connector");
                Connector connector = new Connector(Integer.parseInt(connectorElement.attributeValue("port")));
                connector.setMapper(mapper);
                Engine  engine = new Engine(hosts);

                Service service = new Service(engine,connector);
                server.addService(service);
            }



            server.init();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

/*    private void loadServlet() {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> sevlets = rootElement.selectNodes("//servlet");
            for (Element sevlet : sevlets) {
                Element servletNameElement =(Element) sevlet.selectSingleNode("servlet-name");
                Element servletClassElement =(Element) sevlet.selectSingleNode("servlet-class");

                String servletName = servletNameElement.getStringValue();
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");

                Element node =(Element) servletMapping.selectSingleNode("url-pattern");
                String servletClassName = servletClassElement.getStringValue();

                servletMap.put(node.getStringValue(),(Servlet)Class.forName(servletClassName).getConstructor().newInstance());

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/


    private void loadWebAppsDir(Host host) throws FileNotFoundException {
        File file = new File(host.getAppBase());
        if (!file.exists() && !file.isDirectory()){
            return;
        }
        File[] files = file.listFiles();
        for (File app : files) {
            if (!app.isDirectory()){
                continue;
            }
            String name = app.getName();
            if (host.getContexts().parallelStream().anyMatch(context -> context.getDocBase().equals(name))){
                //判断是否已经被加载过
                continue;
            }
            Context context = new Context(name, name);
            loadWebServlet(host.getAppBase(),context);
            host.addContext(context);
            mapper.addContext(host.getName(),context);
        }
    }
    /**
     * 加载 context指定的目录下的servlet
     * @param path
     * @param context
     * @throws FileNotFoundException
     */
    private void loadWebServlet(String path, Context context) throws FileNotFoundException {
        String dirPath = path + File.separator + context.getDocBase();
        File file = new File(dirPath);
        if (!file.exists() && !file.isDirectory()){
            return;
        }
        //使用自定义加载器
        ClassLoader classLoader = new LagouClassLoader(dirPath);
        //判断有没有配置web.xml，没有，这不初始化servlet
        File webXml = new File(file.getAbsolutePath() + File.separator + "web.xml");
        if (!webXml.exists()){
            return;
        }
        InputStream resourceAsStream = new FileInputStream(webXml);
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> sevlets = rootElement.selectNodes("//servlet");
            for (Element sevlet : sevlets) {
                Element servletNameElement =(Element) sevlet.selectSingleNode("servlet-name");
                Element servletClassElement =(Element) sevlet.selectSingleNode("servlet-class");

                String servletName = servletNameElement.getStringValue();
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");

                Element node =(Element) servletMapping.selectSingleNode("url-pattern");
                String servletClassName = servletClassElement.getStringValue();
                String urlPattern = node.getStringValue();


                Servlet servlet = (Servlet) classLoader.loadClass(servletClassName).getConstructor().newInstance();
                context.addWrapper(new Wrapper(urlPattern,servlet));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void start() throws Exception {
       /* ServerSocket serverSocket = new ServerSocket(port);

        int corePoolSize = 10;
        int maximumPoolSize =50;
        long keepAliveTime = 100L;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();


        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler
        );*/

//        while (true) {
            // v1.0
//            Socket socket = serverSocket.accept();
//            String result = "Hello Minicat";
//            OutputStream outputStream = socket.getOutputStream();
//            outputStream.write(HttpProtocolUtil.getHttpResultString(result).getBytes());
//            socket.close();

            //v2.0 实现静态文件返回
/*            Socket socket = serverSocket.accept();
            Request request = new Request(socket.getInputStream());
            Response response = new Response(socket.getOutputStream());
            response.outputStatic(request.getUrl());
            socket.close();*/

            //v3.0 bio
           /* Socket socket = serverSocket.accept();
            Request request = new Request(socket.getInputStream());
            Response response = new Response(socket.getOutputStream());
            Servlet servlet = servletMap.get(request.getUrl());
            if (servlet == null){
                //如果找不到servlet，尝试返回静态页面
                response.outputStatic(request.getUrl());
            }else {
                servlet.service(request,response);
            }
            socket.close();*/

            //v4.0
//            Socket socket = serverSocket.accept();
//            RequestProcessor processor = new RequestProcessor(socket,servletMap);
//            processor.start();
            //v5.0
/*
            Socket socket = serverSocket.accept();
            RequestProcessor processor = new RequestProcessor(socket,servletMap);
            threadPoolExecutor.execute(processor);
*/


//        }
        server.start();
    }

    public static void main(String[] args) throws Exception {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.init();
        bootstrap.start();

    }
}
